using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Reactive;
using Avalonia;
using Avalonia.Threading;
using DynamicData;
using NLog;
using ReactiveUI;
using SocketTool.Controls;
using SocketTool.Model;
using SocketTool.Model.BindingModels;
using SocketTool.Model.DataModels;
using SocketTool.Model.DataModels.DbModel;
using SocketTool.Views.DialogWindows;

namespace SocketTool.ViewModels.Protocols
{
    public class ProtocolManageViewModel : ViewModelBase
    {
        private ILogger _logger;
        private SocketTool.Dll.ProtocolGroupDll _protocolGroupCache;
        private SocketTool.Dll.JsonProtocolsDll _jsonProtocolCache;

        #region Properties

        private ProtocolGroupBindingModel mSelectedProtocolGroup;

        /// <summary>
        /// 当前选中的协议分组
        /// </summary>
        public ProtocolGroupBindingModel SelectedProtocolGroup
        {
            get => this.mSelectedProtocolGroup;
            set
            {
                this.RaiseAndSetIfChanged(ref this.mSelectedProtocolGroup, value);
                this.SelectedGroupChanged();
            }
        }

        /// <summary>
        /// 左侧协议分组列表信息
        /// </summary>
        public IList<ProtocolGroupBindingModel> ProtocolGroupList { get; private set; }


        private string mSearchContent;

        /// <summary>
        /// 搜索内容
        /// </summary>
        public string SearchContent
        {
            get => this.mSearchContent;
            set => this.RaiseAndSetIfChanged(ref this.mSearchContent, value);
        }

        private bool mIsCheckAll;

        /// <summary>
        /// 协议头是否全选
        /// </summary>
        public bool IsCheckAll
        {
            get => this.mIsCheckAll;
            set => this.RaiseAndSetIfChanged(ref this.mIsCheckAll, value);
        }


        /// <summary>
        /// 协议头信息
        /// </summary>
        public IList<ProtocolHeadInfoBindingModel> ProtocolHeadList { get; private set; }


        private bool mIsShowEdit = false;

        /// <summary>
        /// 是否显示编辑页面
        /// </summary>
        public bool IsShowEdit
        {
            get => this.mIsShowEdit;
            set => this.RaiseAndSetIfChanged(ref this.mIsShowEdit, value);
        }

        #region EditInfo

        /// <summary>
        /// 编辑中的协议ID
        /// </summary>
        private string editProtocolId;

        private string protocolHead;

        /// <summary>
        /// 编辑的协议头
        /// </summary>
        public string ProtocolHead
        {
            get => this.protocolHead;
            set => this.RaiseAndSetIfChanged(ref this.protocolHead, value);
        }

        private string protocolCode;

        /// <summary>
        /// 协议码
        /// </summary>
        public string ProtocolCode
        {
            get => this.protocolCode;
            set => this.RaiseAndSetIfChanged(ref this.protocolCode, value);
        }

        private string protocolExplan;

        /// <summary>
        /// 协议备注说明
        /// </summary>
        public string ProtocolExplan
        {
            get => this.protocolExplan;
            set => this.RaiseAndSetIfChanged(ref this.protocolExplan, value);
        }

        private ViewModels.ControlViewModel.ReqMessageParamViewModel _paramViewModel;

        /// <summary>
        /// 获取请求参数输入控件的ViewModel
        /// </summary>
        public ViewModels.ControlViewModel.ReqMessageParamViewModel ParamViewModel
        {
            get
            {
                if (_paramViewModel == null)
                    _paramViewModel = GlobalContext.Current.CurrentProtocolManageView.GetReqParamVMContext();
                return _paramViewModel;
            }
        }

        #endregion

        #endregion

        #region Commands

        /// <summary>
        /// 创建协议分组信息
        /// </summary>
        public ReactiveCommand<Unit, Unit> CreateProtocolGroupCommand { get; private set; }

        /// <summary>
        /// 搜索
        /// </summary>
        public ReactiveCommand<Unit, Unit> SearchProtocolCommand { get; private set; }

        /// <summary>
        /// 重置搜索
        /// </summary>
        public ReactiveCommand<Unit, Unit> ResetSearchCommand { get; private set; }

        /// <summary>
        /// 添加新协议
        /// </summary>
        public ReactiveCommand<Unit, Unit> AddNewProtocolCommand { get; private set; }

        /// <summary>
        /// 清空所有协议信息
        /// </summary>
        public ReactiveCommand<Unit, Unit> ClearProtocolCommand { get; private set; }

        /// <summary>
        /// 协议导出
        /// </summary>
        public ReactiveCommand<Unit, Unit> ProtocolOutputCommand { get; private set; }

        /// <summary>
        /// 编辑协议信息
        /// </summary>
        public ReactiveCommand<string, Unit> EditProtocolCommand { get; private set; }

        /// <summary>
        /// 移除单条协议信息
        /// </summary>
        public ReactiveCommand<string, Unit> RemoveProtocolCommand { get; private set; }

        /// <summary>
        /// 保存编辑后的协议信息
        /// </summary>
        public ReactiveCommand<Unit, Unit> SaveEditCommand { get; private set; }

        #endregion

        public ProtocolManageViewModel(SocketTool.Dll.ProtocolGroupDll protocolGroup,
            SocketTool.Dll.JsonProtocolsDll jsonProtocols,
            ILogger logger)
        {
            this._protocolGroupCache = protocolGroup;
            this._jsonProtocolCache = jsonProtocols;
            this._logger = logger;

            this.ProtocolGroupList = new ObservableCollection<ProtocolGroupBindingModel>();
            this.ProtocolHeadList = new ObservableCollection<ProtocolHeadInfoBindingModel>();

            this.CreateProtocolGroupCommand = ReactiveCommand.Create(this.CreateProtocolGroup);
            this.SearchProtocolCommand = ReactiveCommand.Create(SearchProtocol);
            this.ResetSearchCommand = ReactiveCommand.Create(this.ResetSearch);
            this.AddNewProtocolCommand = ReactiveCommand.Create(this.AddNewProtocol);
            this.ClearProtocolCommand = ReactiveCommand.Create(this.ClearProtocol);
            this.ProtocolOutputCommand = ReactiveCommand.Create(this.OutputProtocol);
            this.EditProtocolCommand = ReactiveCommand.Create<string>(this.EditProtocol);
            this.RemoveProtocolCommand = ReactiveCommand.Create<string>(RemoveProtocol);
            this.SaveEditCommand = ReactiveCommand.Create(this.SaveProtocol);

            this.InitProtocolGroupInfo();
        }

        #region 协议分组

        /// <summary>
        /// 添加协议分组信息
        /// </summary>
        void CreateProtocolGroup()
        {
            int newRowId = this._protocolGroupCache.AddNewProtocolGroup($"新分组信息");
            var newGroup = new ProtocolGroupBindingModel()
            {
                GroupId = newRowId,
                Index = this.ProtocolGroupList.Count + 1,
                EditName = "新分组信息",
                IsEditing = true
            };
            this.ProtocolGroupList.Add(newGroup);
            this.SelectedProtocolGroup = newGroup;
        }

        /// <summary>
        /// 协议分组重命名
        /// </summary>
        /// <param name="group"></param>
        public void ProtocolGroupReName(ProtocolGroupBindingModel group)
        {
            this._protocolGroupCache.UpdateProtocolGroup(new ProtocolGroup()
                {GroupId = group.GroupId, GroupName = group.EditName});
            group.GroupName = group.EditName;
            group.IsEditing = false;
        }

        /// <summary>
        /// 协议分组删除
        /// </summary>
        /// <param name="group"></param>
        public void ProtocolGroupRemove(ProtocolGroupBindingModel group)
        {
            //默认分组不可删除
            if (group.GroupId == 1)
            {
                Views.DialogWindows.MessageDialogWindow.ShowTipsDialog("默认分组不可删除!");
                return;
            }

            //删除新增中的项
            if (group.GroupId == 0)
            {
                this.ProtocolGroupList.Remove(group);
                return;
            }

            var flag = this._protocolGroupCache.DeleteProtocolGroup(group.GroupId);
            if (flag)
            {
                this.ProtocolGroupList.Remove(group);
            }
        }

        #endregion

        /// <summary>
        /// 选中分组改变事件
        /// </summary>
        private void SelectedGroupChanged()
        {
            this.SearchContent = string.Empty;
            this.SearchProtocol();
        }

        /// <summary>
        /// 搜索协议信息
        /// </summary>
        private void SearchProtocol()
        {
            try
            {
                this.ProtocolHeadList.Clear();
                List<ProtocolInfoModel> queryList = null;
                if (string.IsNullOrEmpty(this.SearchContent))
                    queryList = this._jsonProtocolCache.QueryProtocols(this.SelectedProtocolGroup.GroupId);
                else
                    queryList = this._jsonProtocolCache.QueryProtocolsForName(this.SearchContent,
                        this.SelectedProtocolGroup.GroupId);

                if (queryList == null || queryList.Count < 1)
                    return;
                foreach (var item in queryList)
                {
                    this.ProtocolHeadList.Add(new()
                    {
                        GroupId = this.SelectedProtocolGroup.GroupId,
                        ProtocolId = item.ProtocolId,
                        Index = this.ProtocolHeadList.Count() + 1,
                        ProtocolName = item.ProtocolName,
                        ProtocolCode = item.ProtocolCode,
                        ProtocolExplan = item.ProtocolExplan
                    });
                }
            }
            catch (Exception ex)
            {
                this._logger.Error(ex);
            }
        }

        /// <summary>
        /// 重置搜索
        /// </summary>
        private void ResetSearch()
        {
            this.SearchContent = string.Empty;
            this.SearchProtocol();
        }

        /// <summary>
        /// 添加新协议
        /// </summary>
        private void AddNewProtocol()
        {
            this.editProtocolId = string.Empty;
            this.ProtocolHead = string.Empty;
            this.ProtocolCode = string.Empty;
            this.ProtocolExplan = string.Empty;
            this.ParamViewModel.ClearParam();
            this.IsShowEdit = true;
        }

        /// <summary>
        /// 删除选中的协议
        /// </summary>
        private void ClearProtocol()
        {
            try
            {
                var deleteIdList = this.ProtocolHeadList.Where(w => w.IsCheck).Select(s => s.ProtocolId).ToList();
                var flag = this._jsonProtocolCache.DeleteProtocolList(deleteIdList);
                if (flag)
                {
                    foreach (var item in deleteIdList)
                    {
                        var cache = this.ProtocolHeadList.FirstOrDefault(f => f.ProtocolId == item);
                        if (cache != null)
                            this.ProtocolHeadList.Remove(cache);
                    }
                }
            }
            catch (Exception ex)
            {
                this._logger.Error(ex);
            }
        }

        /// <summary>
        /// 导出选中的协议
        /// </summary>
        private void OutputProtocol()
        {
            GrowlControl.Error("None Protocol Info!");
        }

        /// <summary>
        /// 编辑协议信息
        /// </summary>
        /// <param name="protocolId"></param>
        private void EditProtocol(string protocolId)
        {
            try
            {
                var editModel = this._jsonProtocolCache.QueryProtocol(protocolId);
                if (editModel == null)
                    return;

                this.ProtocolHead = editModel.ProtocolName;
                this.ProtocolCode = editModel.ProtocolCode;
                this.ProtocolExplan = editModel.ProtocolExplan;
                this.editProtocolId = editModel.ProtocolId;
                var saveParamList =
                    Newtonsoft.Json.JsonConvert
                        .DeserializeObject<List<ProtocolContentModel>>(editModel.ProtocolContent);
                IList<ReqParamBindingModel> bindingList = new List<ReqParamBindingModel>();
                this.SetAllParams(saveParamList, bindingList, null);
                this.ParamViewModel.SetJsonParam(bindingList);

                this.IsShowEdit = true;
            }
            catch (Exception ex)
            {
                this._logger.Error(ex);
            }
        }

        /// <summary>
        /// 删除单条协议
        /// </summary>
        /// <param name="protocolId"></param>
        private void RemoveProtocol(string protocolId)
        {
            try
            {
                Views.DialogWindows.ConfirmMessageDialogWindow confirm = new ConfirmMessageDialogWindow("是否删除协议");
                confirm.ShowDialog(App.MainWindow).ContinueWith(r =>
                {
                    if (confirm.DialogResult != true)
                        return;
                    var flag = this._jsonProtocolCache.DeleteProtocol(protocolId);
                    if (flag)
                    {
                        var cache = this.ProtocolHeadList.FirstOrDefault(f => f.ProtocolId == protocolId);
                        if (cache != null)
                        {
                            Dispatcher.UIThread.InvokeAsync(() => { this.ProtocolHeadList.Remove(cache); },
                                DispatcherPriority.Normal);
                        }
                    }
                });
            }
            catch (Exception ex)
            {
                this._logger.Error(ex);
            }
        }

        /// <summary>
        /// 保存协议信息
        /// </summary>
        private void SaveProtocol()
        {
            try
            {
                if (this.ProtocolHead.Length > 30 || this.ProtocolHead.Length < 2)
                {
                    GrowlControl.Warning("协议名称式不正确!");
                    return;
                }

                if (this.ProtocolCode.Length < 2 || this.protocolCode.Length > 30)
                {
                    GrowlControl.Warning("协议码格式不正确!");
                    return;
                }

                if (this.ProtocolExplan.Length > 300)
                {
                    GrowlControl.Warning($"协议说明字数超过300个：{this.ProtocolExplan.Length}/300!");
                    return;
                }

                if (this.ParamViewModel.SelectedTextParam)
                    this.ParamViewModel.InitJsonParamFromText();
                if (this.ParamViewModel.ParamsList.Count < 1)
                {
                    SocketTool.Controls.GrowlControl.Warning("协议内容为空！");
                    return;
                }
                
                List<ProtocolContentModel> contentList = new List<ProtocolContentModel>();
                this.GetAllParams(this.ParamViewModel.ParamsList, contentList, null);


                ProtocolInfoModel saveModel = new()
                {
                    GroupId = this.SelectedProtocolGroup.GroupId,
                    ProtocolId = this.editProtocolId,
                    ProtocolCode = this.ProtocolCode,
                    ProtocolName = this.ProtocolHead,
                    ProtocolExplan = this.ProtocolExplan,
                    ProtocolContent = Newtonsoft.Json.JsonConvert.SerializeObject(contentList)
                };

                //新增协议信息
                if (string.IsNullOrEmpty(this.editProtocolId))
                {
                    saveModel.ProtocolId = GlobalContext.Current.CreateProtocolHeadID();
                    var success = this._jsonProtocolCache.AddNewProtocolInfo(saveModel);
                    if (!success)
                    {
                        GrowlControl.Warning("协议保存失败!");
                        return;
                    }

                    this.ProtocolHeadList.Add(new ProtocolHeadInfoBindingModel()
                    {
                        GroupId = this.SelectedProtocolGroup.GroupId,
                        ProtocolId = saveModel.ProtocolId,
                        Index = this.ProtocolHeadList.Count() + 1,
                        ProtocolName = saveModel.ProtocolName,
                        ProtocolCode = saveModel.ProtocolCode,
                        ProtocolExplan = saveModel.ProtocolExplan
                    });
                    this.IsShowEdit = false;
                }
                else
                {
                    var success = this._jsonProtocolCache.UpdateProtocolInfo(saveModel);
                    if (!success)
                    {
                        GrowlControl.Warning("协议保存失败!");
                        return;
                    }

                    var cache = this.ProtocolHeadList.FirstOrDefault(w => w.ProtocolId == this.editProtocolId);
                    if (cache != null)
                    {
                        cache.ProtocolName = saveModel.ProtocolName;
                        cache.ProtocolCode = saveModel.ProtocolCode;
                        cache.ProtocolExplan = saveModel.ProtocolExplan;
                    }
                }
            }
            catch (Exception ex)
            {
                this._logger.Error(ex);
            }
        }

        /// <summary>
        /// 初始化协议分组信息
        /// </summary>
        private void InitProtocolGroupInfo()
        {
            var allGroupList = this._protocolGroupCache.GetProtocolGroupList();
            if (allGroupList == null || allGroupList.Count < 1)
                return;

            foreach (var item in allGroupList)
            {
                ProtocolGroupBindingModel bdModel = new ProtocolGroupBindingModel();
                bdModel.Index = this.ProtocolGroupList.Count + 1;
                bdModel.GroupId = item.GroupId;
                bdModel.GroupName = item.GroupName;
                bdModel.EditName = item.GroupName;
                this.ProtocolGroupList.Add(bdModel);
            }
        }

        /// <summary>
        /// 将ReqParamBindingModel 转换为 ProtocoContentModel
        /// </summary>
        /// <param name="source"></param>
        /// <param name="outList"></param>
        /// <param name="protocolHeadId"></param>
        private void GetAllParams(IList<ReqParamBindingModel> source, IList<ProtocolContentModel> outList,
            ProtocolContentModel content)
        {
            if (source.Count < 1)
                return;
            foreach (var item in source)
            {
                var contentModel = new ProtocolContentModel()
                {
                    Key = item.Key,
                    Value = item.Value,
                    ValueType = (Model.Enums.JsonValueTypeEnum) item.ValueType,
                    Explan = item.Explan
                };
                if (content == null)
                    outList.Add(contentModel);
                else
                    content.Children.Add(contentModel);

                if (item.Children.Count > 0)
                {
                    GetAllParams(item.Children, outList, contentModel);
                }
            }
        }

        /// <summary>
        /// 将ProtocolContentModel 转换为 ReqParamBindingModel
        /// </summary>
        /// <param name="cacheList"></param>
        /// <param name="bindingList"></param>
        private void SetAllParams(IList<ProtocolContentModel> cacheList, IList<ReqParamBindingModel> bindingList,
            ReqParamBindingModel parent = null)
        {
            if (cacheList.Count < 1)
                return;

            foreach (var item in cacheList)
            {
                var bindingModel = new ReqParamBindingModel(parent)
                {
                    Key = item.Key,
                    Value = item.Value?.ToString(),
                    ValueType = (int) item.ValueType,
                    Explan = item.Explan,
                    HasChild = item.Children.Any(),
                };
                if (parent == null)
                    bindingList.Add(bindingModel);
                else
                    parent.Children.Add(bindingModel);

                SetAllParams(item.Children, bindingList, bindingModel);
            }
        }
    }
}